package com.bridgeintelligent.tag.customer.looklike;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.bridgeintelligent.tag.constants.bulkload.LookLikeMqMsg;
import com.bridgeintelligent.tag.constants.bulkload.MQConfig;
import com.bridgeintelligent.tag.customer.exception.CustomerErrors;
import com.bridgeintelligent.tag.customer.mapper.CustomersMapper;
import com.bridgeintelligent.tag.customer.mapper.LookLikeMapper;
import com.bridgeintelligent.tag.customer.mapper.QueryModelMapper;
import com.bridgeintelligent.tag.customer.model.CustomerModel;
import com.bridgeintelligent.tag.customer.pojo.Filter;
import com.bridgeintelligent.tag.customer.pojo.FilterGroup;
import com.bridgeintelligent.tag.customer.pojo.QueryModel;
import com.bridgeintelligent.tag.customer.query.QueryApi;
import com.bridgeintelligent.tag.customer.query.QueryApiUtils;
import com.bridgeintelligent.tag.user.mgmt.pojo.User;
import com.bridgeintelligent.tag.utils.DateHelper;
import com.bridgeintelligent.tag.webserver.security.TagSecurityHelper;
import com.bridgeintelligent.tag.utils.FieldHandler;
import com.bridgeintelligent.tag.webserver.system.entity.DimUseRecord;
import com.bridgeintelligent.tag.webserver.system.service.DimUseRecordService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wayneleo.quickstart.QuickException;
import com.wayneleo.quickstart.framework.IDGenerator;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
@Slf4j
public class LookLikeServiceImpl implements ILookLikeService {

    private static final String PRIFIX = "looklike_";

    protected RocketMQTemplate rocketMQTemplate;

    private LookLikeMapper lookLikeMapper;

    private CustomersMapper customersMapper;

    private ObjectMapper objectMapper;

    private QueryModelMapper queryModelMapper;

    private QueryApiUtils queryApiUtils;

    private DimUseRecordService dimUseRecordService;

    @SneakyThrows
    @Override
    public void addLookLike(LookLikeInfo lookLikeInfo) {
        User user = TagSecurityHelper.currentUser();
        lookLikeInfo.setId(IDGenerator.gen())
                    .setIsAnalysis(AnalysisEnum.ANALYSIS_ONE.getCode())
                    .setIsDel(ChoiceEnum.CHOICE_ZERO.getCode())
                    .setSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                    .setBlackSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                    .setWhiteSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                    .setCustomerSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                    .setUserId(user.getUserId())
                    .setUserName(user.getName())
                    .setCreateTime(DateHelper.currentDateTime(DateHelper.PATTERN_DATE_1))
                    .setUpdateTime(DateHelper.currentDateTime(DateHelper.PATTERN_DATE_1))
                    .setIsHandler(ChoiceEnum.CHOICE_ZERO.getCode());
        if(ChoiceEnum.CHOICE_ONE.getCode().equals(lookLikeInfo.getIsUseCustomerPool())){
            QueryModel queryModel = objectMapper.readValue(lookLikeInfo.getConfig(), QueryModel.class);
            //调用客群筛选接口
            Long customerCount = getCustomerCount(lookLikeInfo.getConfig(),lookLikeInfo.getConfigStatic());
            int custAmount = lookLikeInfo.getCustAmount();
            if(customerCount<custAmount){
                throw new RuntimeException("筛选客群的客数：["+customerCount+"]应该大于扩散相似客群数：["+custAmount+"]，请重新配置筛选条件再进行保存");
            }
            lookLikeInfo.setCustomerSeedFilterGroup(objectMapper.writeValueAsString(queryModel.getFilterGroup()));
        }
        lookLikeMapper.addLookLike(lookLikeInfo);
        //增加操作记录
        this.addOperation(OperationEnum.CREATE.getCode(),lookLikeInfo.getId());
        //保存标签使用记录
        if (StrUtil.isNotBlank(lookLikeInfo.getDimIds())){
            dimUseRecordService.addRecord(DimUseRecord.of().setId(lookLikeInfo.getId()).setDataType("4").setDimId(lookLikeInfo.getDimIds()).setCreateTime(DateHelper.currentDateTime()));
        }
    }

    //获取筛选客群数量
    private long getCustomerCount(String config,String configStatic){
        QueryApi queryApi = queryApiUtils.build(QueryApi.class);

        //静态客群
        if(StringUtils.isNotEmpty(configStatic)){
            return queryApi.analysisCount(configStatic).getTotalCount();
        }
        //动态客群
        return queryApi.analysisCount(config).getTotalCount();

    }
    @SneakyThrows
    @Override
    public void updateLookLike(LookLikeInfo lookLikeInfo) {
        //先查询数据库数据
        LookLikeInfo dbLike = lookLikeMapper.findById(lookLikeInfo.getId());
        if (dbLike != null){
            lookLikeInfo.setSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                        .setBlackSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                        .setWhiteSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                        .setCustomerSeedStatus(ChoiceEnum.CHOICE_ZERO.getCode())
                        .setIsAnalysis(AnalysisEnum.ANALYSIS_ONE.getCode())
                        .setCreateTime(dbLike.getCreateTime())
                        .setUpdateTime(DateHelper.currentDateTime(DateHelper.PATTERN_DATE_1))
                        .setIsDel(ChoiceEnum.CHOICE_ZERO.getCode())
                        .setIsHandler(ChoiceEnum.CHOICE_ZERO.getCode());
            lookLikeMapper.delReal(lookLikeInfo.getId());
            if(ChoiceEnum.CHOICE_ONE.getCode().equals(lookLikeInfo.getIsUseCustomerPool())){
                QueryModel queryModel = objectMapper.readValue(lookLikeInfo.getConfig(), QueryModel.class);
                //调用客群筛选接口
                Long customerCount = getCustomerCount(lookLikeInfo.getConfig(),lookLikeInfo.getConfigStatic());
                int custAmount = lookLikeInfo.getCustAmount();
                if(customerCount<custAmount){
                    throw new RuntimeException("筛选客群的客数：["+customerCount+"]应该大于扩散相似客群数：["+custAmount+"]，请重新配置筛选条件再进行保存");
                }
                lookLikeInfo.setCustomerSeedFilterGroup(objectMapper.writeValueAsString(queryModel.getFilterGroup()));
            }
            lookLikeMapper.addLookLike(lookLikeInfo);
            //增加操作记录
            this.addOperation(OperationEnum.UPDATE.getCode(),lookLikeInfo.getId());

            //保存标签使用记录
            if (StrUtil.isNotBlank(lookLikeInfo.getDimIds())){
                dimUseRecordService.addRecord(DimUseRecord.of().setId(lookLikeInfo.getId()).setDataType("4").setDimId(lookLikeInfo.getDimIds()).setCreateTime(DateHelper.currentDateTime()));
            }
        }
    }

    @Override
    public boolean checkName(String id,String lookName) {
        String dbId = lookLikeMapper.checkName(lookName);
        if (StringUtils.isEmpty(dbId)){
            return false;
        }else{
            if (!StringUtils.isEmpty(id) && StringUtils.equals(id,dbId)){
                return false;
            }
        }
        return true;
    }

    @SneakyThrows
    @Override
    public LookLikeInfo findById(String id) {
        LookLikeInfo info = Objects.requireNonNull(lookLikeMapper.findById(id));

        List<LookLikeOperation> lookLikeOperations = lookLikeMapper.operationList(id);
        if (CollectionUtils.isEmpty(lookLikeOperations)){
            lookLikeOperations = new ArrayList<>();
        }
        info.setOperationList(lookLikeOperations);

        if(!StringUtils.isEmpty(info.getFields())){
            //处理标签中文名字
            String dimName = "";
            List<String> dimIds = Arrays.asList(info.getFields().split(","));
            Map<String, String> dimMsg = new HashMap<>();
            for (String field : dimIds) {
                //查出输出标签名
                dimName = queryModelMapper.findDimNameById(field);
                dimMsg.put(field, dimName);
            }
            info.setDimMsg(dimMsg);
        }
        //处理筛选条件数组
        if(StringUtils.isNotEmpty(info.getConfig())){
            QueryModel queryModel = objectMapper.readValue(info.getConfig(), QueryModel.class);
            List<Filter> filterList = new ArrayList<>();
            getFiltersList(queryModel.getFilterGroup(),filterList);
            info.setFilterList(filterList);
        }
        return info;
    }
    private void getFiltersList(FilterGroup filterGroup,List<Filter> filterList){
        if(CollectionUtils.isNotEmpty(filterGroup.getFilters())){
            filterList.addAll(filterGroup.getFilters());
        }
        if(CollectionUtils.isNotEmpty(filterGroup.getChildren())){
            for(FilterGroup group:filterGroup.getChildren()){
                getFiltersList(group,filterList);
            }
        }
    }
    @Override
    public void delById(String id) {
        lookLikeMapper.delById(id,DateHelper.currentDateTime(DateHelper.PATTERN_DATE_1));
    }

    @Override
    public LookLikePage<LookLikeInfo> findList(String lookName, String isAnalysis, String stTime, String edTime, Integer pageNum, Integer pageSize) {
        User user = TagSecurityHelper.currentUser();
        pageNum = pageNum == null ? 1 : pageNum;
        pageSize = pageSize == null ? 10 : pageSize;
        String userId = user.getUserId();
        if (FieldHandler.isUnionAdmin(user.getRoleId())){
            userId = "";
        }
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<LookLikeInfo> list = lookLikeMapper.findList(lookName, isAnalysis, stTime, edTime, userId);
        LookLikePage<LookLikeInfo> lookLikePage = new LookLikePage<>();
        lookLikePage.setContent(list)
                    .setTotalPages(page.getPages())
                    .setTotalElements(page.getTotal())
                    .setSize(page.getPageSize())
                    .setRequestPage(pageNum);
        return lookLikePage;
    }

    @Override
    public void readyData(String id) {
        //现根据id查询相似客群的基础信息
        LookLikeInfo info = lookLikeMapper.findById(id);
        //先将状态置为02运算中，同时把三个数据文件字段置为00未开始，且生成一个索引
        Map<String,String> param1 = new HashMap<>();
        param1.put("id",id);
        param1.put("isAnalysis",AnalysisEnum.ANALYSIS_TWO.getCode());
        param1.put("seedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        param1.put("blackSeedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        param1.put("whiteSeedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        param1.put("customerSeedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        String esIndex = PRIFIX+DateHelper.currentDateTime(DateHelper.PATTERN_DATE_7);
        param1.put("esIndex",esIndex);
        lookLikeMapper.updateDataStatus(param1);

        this.addOperation(OperationEnum.UP.getCode(),info.getId());//增加操作记录
        //处理种子数据
        sendMqMessage(id,info.getSeedId(),ChoiceEnum.CHOICE_ZERO.getCode(),esIndex);
        //处理黑名单数据
        if (StringUtils.equals(info.getIsBlack(),ChoiceEnum.CHOICE_ONE.getCode())){
            sendMqMessage(id,info.getBlackSeedId(),ChoiceEnum.CHOICE_ONE.getCode(),esIndex);
        }
        //处理白名单数据
        if (StringUtils.equals(info.getIsWhite(),ChoiceEnum.CHOICE_ONE.getCode())){
            sendMqMessage(id,info.getWhiteSeedId(),ChoiceEnum.CHOICE_TWO.getCode(),esIndex);
        }
        //处理筛选客群数据
        if (StringUtils.equals(info.getIsUseCustomerPool(),ChoiceEnum.CHOICE_ONE.getCode())){
            sendMqMessage(id,info.getCustomerSeedId(),ChoiceEnum.CHOICE_THIRD.getCode(),esIndex);
        }
    }

    @Override
    public void updateDataStatus(String isAnalysis, String seedStatus, String blackSeedStatus, String whiteSeedStatus, String id) {
        Map<String,String> param = new HashMap<>();
        param.put("id",id);
        param.put("isAnalysis",AnalysisEnum.ANALYSIS_TWO.getCode());
        param.put("seedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        param.put("blackSeedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        param.put("whiteSeedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        param.put("customerSeedStatus",ChoiceEnum.CHOICE_ZERO.getCode());
        lookLikeMapper.updateDataStatus(param);
    }

    @Override
    public void makeExpire() {
        List<String> list = lookLikeMapper.expireList(DateHelper.currentDateTime(DateHelper.PATTERN_DATE_1));
        Map<String,String> param = new HashMap<>();
        param.put("isAnalysis",AnalysisEnum.ANALYSIS_FIVE.getCode());
        if (!CollectionUtils.isEmpty(list)){
            list.forEach(e->{
                param.put("id",e);
                lookLikeMapper.updateDataStatus(param);
            });
        }
    }

    @Override
    public LookLikePage<LookLikeCharacter> findCharacterList(String lookId,String dimName, Integer pageNum, Integer pageSize) {
        pageNum = pageNum == null ? 1 : pageNum;
        pageSize = pageSize == null ? 10 : pageSize;
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<LookLikeCharacter> list = lookLikeMapper.findCharacterList(dimName,lookId);
        LookLikePage<LookLikeCharacter> lookLikePage = new LookLikePage<>();
        lookLikePage.setContent(list)
                .setTotalPages(page.getPages())
                .setTotalElements(page.getTotal())
                .setSize(page.getPageSize())
                .setRequestPage(pageNum);
        return lookLikePage;
    }

    @Override
    public List<CustomerModel> lookCustomerList(String indexId, String customerName,String num) {
        User user = TagSecurityHelper.currentUser();
        Double count = null;
        if (!StringUtils.isEmpty(num)){
            count = Double.parseDouble(num);
        }
        if (FieldHandler.isUnionAdmin(user.getRoleId())){
            //如果是超管
            return lookLikeMapper.unionAdminLookCustomerList(indexId,customerName,count);
        }else{
            return lookLikeMapper.commonLookCustomerList(indexId,customerName,user.getUserId(),count);
        }
    }

    @Override
    public void addOperation(String code,String lookId) {
        User user = TagSecurityHelper.currentUser();
        LookLikeOperation operation = new LookLikeOperation();
        operation.setId(IDGenerator.gen())
                .setLookId(lookId)
                .setOperationType(code)
                .setOperationName(OperationEnum.getName(code))
                .setUserId(user.getUserId())
                .setUserName(user.getUsername())
                .setDateTime(DateHelper.currentDateTime());
        lookLikeMapper.addOperation(operation);
    }


    private void sendMqMessage(String id,String customerId,String type,String esIndex){
        try {
            //封装message信息
            LookLikeMqMsg message = new LookLikeMqMsg();
            message.setId(id).setCustomerId(customerId).setType(type).setEsIndex(esIndex).setUniqueIdentify(id+"_"+ RandomUtil.randomString(6));
            String msg = objectMapper.writeValueAsString(message);
            rocketMQTemplate.convertAndSend(MQConfig.LOOK_LIKE_TOPIC, msg);
            //发送成功将数据文件状态置为处理中
            updateStatus(type,"",ChoiceEnum.CHOICE_ONE.getCode(),id);
        }catch (Exception e) {
            //发送失败将客群状态置为失败
            updateStatus(type,AnalysisEnum.ANALYSIS_FOUR.getCode(),ChoiceEnum.CHOICE_THIRD.getCode(),id);
            throw QuickException.normal(CustomerErrors.ERROR_401004.args(id,type),e);
        }
    }


    private void updateStatus(String type,String isAnalysis,String status,String id){
        Map<String,String> param = new HashMap<>();
        param.put("id",id);
        param.put("isAnalysis",isAnalysis);
        switch (type) {
            case "00":
                param.put("seedStatus", status);
                break;
            case "01":
                param.put("blackSeedStatus", status);
                break;
            case "02":
                param.put("whiteSeedStatus", status);
                break;
            default:
                param.put("customerSeedStatus", status);
                break;
        }
        lookLikeMapper.updateDataStatus(param);
    }



}
